package com.example.docking.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.example.docking.dao.jindie.GenericDataItem;
import com.example.docking.dao.jindie.PurInvoiceDetail;
import com.example.docking.dao.jindie.ResponseData;
import com.example.docking.dao.jindie.response.*;
import com.example.docking.dao.xky.ReceiptOrderDetailParam;
import com.example.docking.dao.xky.ReceiptOrderLineList;
import com.example.docking.dao.xky.ReceiptOrderPayInfo;
import com.example.docking.httpXKY.dao.BaseXKYObjResponse;
import com.example.docking.httpXKY.httpSend.XKYClient;
import com.example.docking.service.impl.DataServiceImpl;
import com.example.docking.util.Constants;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.smecloud.apigw.model.ApiResult;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

import static com.example.docking.httpXKY.httpSend.XKYClient.ERP_CODE;

/**
 * @author: tengguodong
 * @date: 2025/6/11
 */
@Slf4j
@Controller
public class ERPApCreditController {
    public void selectApCredit() {
        // 1.查询付款单列表
        List<ApCreditItem> apCreditItems = selectApCreditList();
        log.info("付款单列表：{}", JSON.toJSONString(apCreditItems));
        for (ApCreditItem apCreditItem : apCreditItems) {
            // 2.查询付款单详情
            ApCreditDetail apCreditDetail = selectApCreditDetail(apCreditItem.getId());
            log.info("付款单详情：{}", JSON.toJSONString(apCreditDetail));
            if (StringUtils.isNotBlank(apCreditDetail.getRemark()) && apCreditDetail.getRemark().startsWith("同步成功（勿改）：")) {
                log.info("付款单已同步成功，跳过");
                continue;
            }
            // 3.付款单推送XKY
            String xkyNo = saveApCredit(apCreditDetail);
            // 4.金蝶设置remark“同步成功（勿改）”
            if (StringUtils.isNotBlank(xkyNo)) {
                apCreditDetail.setRemark("同步成功（勿改）：xkyNo");
                updateApCredit(apCreditDetail);
            }
        }
    }

    @SneakyThrows
    private String saveApCredit(ApCreditDetail apCreditDetail) {
        ReceiptOrderDetailParam param = new ReceiptOrderDetailParam();
        param.setErpCode(ERP_CODE);
        param.setInnerVendorCode(apCreditDetail.getSupplier_number());
        param.setCurrencyCode(apCreditDetail.getCurrency_number());
        param.setCurrencyName(apCreditDetail.getCurrency_name());
        param.setFormTypeCode("FKD");
        param.setFormTypeName("付款单");
        param.setErpOrgCode(apCreditDetail.getDept_number());
        param.setErpOrgName(apCreditDetail.getDept_name());
        SupplierData supplier = getSupplier(apCreditDetail.getSupplier_id());

        param.setVendorCreditCode(supplier.getTaxpayer_no());
        param.setBankCode(supplier.getBank_code());
        param.setBankName(supplier.getBank());
        param.setBankCardNo(supplier.getBank_account());

        PayEntry payEntry = apCreditDetail.getPay_entry_list().get(0);
        param.setApplyPaymentMethodCode(payEntry.getPay_type_number());
        param.setApplyPaymentMethodName(payEntry.getPay_type_name());
        param.setPayWayCode("");
        param.setPayWayName("");
        param.setRealPaymentMethodCode(payEntry.getPay_type_number());
        param.setRealPaymentMethodName(payEntry.getPay_type_name());

        param.setPublishName(apCreditDetail.getCreator_name());
        param.setCheckName(apCreditDetail.getCreator_name());

        param.setAutoPublish(1);
        param.setAutoAudit(1);
        param.setAutoPay(1);

        setPayInfo(param, apCreditDetail);

        setLineList(param, apCreditDetail);

        String url = "https://openapi.xiekeyun.com/receipt/upload.json";
        String response = XKYClient.sendRequest(url, param);
        log.info("response:{}", response);
        BaseXKYObjResponse<String> xkyObjResponse = JSONObject.parseObject(response, new TypeReference<BaseXKYObjResponse<String>>() {
        }.getType());
        return xkyObjResponse.getData();
    }

    private void setPayInfo(ReceiptOrderDetailParam param, ApCreditDetail apCreditDetail) {
        PayEntry payEntry = apCreditDetail.getPay_entry_list().get(0);
        SettlementAccount settleAccount = getSettlementAccount(payEntry);
        log.info("结算账户：{}", settleAccount);
        param.setPaymentBankCode(settleAccount.getNumber());
        param.setPaymentBankName(settleAccount.getOpening_bank());
        param.setPaymentBankCardNo(settleAccount.getAccount());
        param.setUnionBankNo(settleAccount.getNumber());

        ReceiptOrderPayInfo payInfo = new ReceiptOrderPayInfo();
        payInfo.setPaymentTypeCode(payEntry.getPay_type_id());
        payInfo.setPaymentTypeName(payEntry.getPay_type_name());
        payInfo.setBankCardNo(settleAccount.getAccount());
        payInfo.setBankName(settleAccount.getOpening_bank());
        param.setPayInfo(payInfo);
    }

    @SneakyThrows
    private SettlementAccount getSettlementAccount(PayEntry payEntry) {
        List<SettlementAccount> settlementAccountList = new ArrayList<>();
        DataServiceImpl service = new DataServiceImpl();
        Gson gson = new Gson();
        int page = 1;
        HashMap<String, String> map = new HashMap<>();
        map.put("search", payEntry.getSettle_account_name());
        map.put("page_size", String.valueOf(100));
        List<SettlementAccount> settlementAccounts;
        do {
            map.put("page", String.valueOf(page++));
            ApiResult detailCredit = service.SelectDataList(Constants.SETTLEMENT_ACCOUNT, map, "");
            Type MateriaDataType = new TypeToken<ResponseData<GenericDataItem<SettlementAccount>>>() {
            }.getType();
            ResponseData<GenericDataItem<SettlementAccount>> detailCreditData = gson.fromJson(detailCredit.getBody(), MateriaDataType);
            GenericDataItem<SettlementAccount> genericDataItemCredit = detailCreditData.getData();
            settlementAccounts = genericDataItemCredit.getRows();
            settlementAccountList.addAll(settlementAccounts);
        } while (settlementAccounts.size() >= 100);

        for (SettlementAccount settlementAccount : settlementAccounts) {
            if (Objects.equals(settlementAccount.getId(), payEntry.getSettle_account_id())) {
                return settlementAccount;
            }
        }

        return new SettlementAccount();
    }

    private void setLineList(ReceiptOrderDetailParam param, ApCreditDetail apCreditDetail) {
        List<ReceiptOrderLineList> lineList = new ArrayList<>();
        List<SourceBillEntry> sourceBillEntryList = apCreditDetail.getSource_bill_entry_list();
        for (SourceBillEntry sourceBillEntry : sourceBillEntryList) {
            ReceiptOrderLineList line = new ReceiptOrderLineList();
            PurInvoiceDetail purInvoiceDetail = getPurInvoice(sourceBillEntry.getSrc_bill_id());
            line.setSourceXkNo(purInvoiceDetail.getRemark().substring(8));
            line.setSourceType("2");
            line.setApplyTaxAmount(Double.valueOf(sourceBillEntry.getCur_settle_amount()));
            line.setRealTaxAmount(Double.valueOf(sourceBillEntry.getCur_settle_amount()));
            lineList.add(line);
        }

        param.setLineList(lineList);
    }

    private SupplierData getSupplier(String id) throws Exception {
        DataServiceImpl service = new DataServiceImpl();
        Gson gson = new Gson();
        HashMap<String, String> map = new HashMap<>();
        map.put("id", id);
        ApiResult DataResult = service.SelectDataDetail(Constants.SUPPLIER_DETAIL, map, "");
        Type SupplierDataType = new TypeToken<ResponseData<SupplierData>>() {
        }.getType();
        ResponseData<SupplierData> responseSupplierData = gson.fromJson(DataResult.getBody(), SupplierDataType);
        SupplierData supplierData = responseSupplierData.getData();
        List<AccountEntity> accountEntityList = supplierData.getAccount_entity();
        for (AccountEntity accountEntity : accountEntityList) {
            if (accountEntity.isAcct_is_default()) {
                supplierData.setBank_code(accountEntity.getIncome_bank_code());
                supplierData.setBank(accountEntity.getIncome_bank_name());
                supplierData.setBank_account(accountEntity.getIncome_acc_no());
            }
        }
        return supplierData;
    }

    @SneakyThrows
    private PurInvoiceDetail getPurInvoice(String id) {
        DataServiceImpl service = new DataServiceImpl();
        Gson gson = new Gson();
        HashMap<String, String> map = new HashMap<>();
        map.put("id", id);
        ApiResult DataResult = service.SelectDataDetail(Constants.PUR_INVOICE_DETAIL, map, "");
        Type purInvoiceType = new TypeToken<ResponseData<PurInvoiceDetail>>() {
        }.getType();
        ResponseData<PurInvoiceDetail> responseSupplierData = gson.fromJson(DataResult.getBody(), purInvoiceType);
        return responseSupplierData.getData();
    }

    @SneakyThrows
    private ApCreditDetail selectApCreditDetail(String id) {
        DataServiceImpl service = new DataServiceImpl();
        Gson gson = new Gson();
        HashMap<String, String> map = new HashMap<>();
        map.put("id", id);
        ApiResult result = service.SelectDataDetail(Constants.CREDIT_detail, map, "");
        Type type2 = new TypeToken<ResponseData<ApCreditDetail>>() {
        }.getType();
        ResponseData<ApCreditDetail> response = gson.fromJson(result.getBody(), type2);
        return response.getData();
    }

    @SneakyThrows
    public List<ApCreditItem> selectApCreditList() {
        List<ApCreditItem> result = new ArrayList<>();
        DataServiceImpl service = new DataServiceImpl();
        Gson gson = new Gson();
        int page = 1;
        HashMap<String, String> map = new HashMap<>();
        long currentTimeMillis = System.currentTimeMillis();
        map.put("bill_status", "C");
        map.put("create_end_time", String.valueOf(currentTimeMillis));
        map.put("create_start_time", String.valueOf(currentTimeMillis - 60 * 60 * 1000));
        map.put("page_size", String.valueOf(100));
        List<ApCreditItem> creditData;
        do {
            map.put("page", String.valueOf(page++));
            ApiResult detailCredit = service.SelectDataList(Constants.CREDIT, map, "");
            Type MateriaDataType = new TypeToken<ResponseData<GenericDataItem<ApCreditItem>>>() {
            }.getType();
            ResponseData<GenericDataItem<ApCreditItem>> detailCreditData = gson.fromJson(detailCredit.getBody(), MateriaDataType);
            GenericDataItem<ApCreditItem> genericDataItemCredit = detailCreditData.getData();
            creditData = genericDataItemCredit.getRows();
            result.addAll(creditData);
        } while (creditData.size() >= 100);

        return result;
    }

    /**
     * 回写单号到金蝶
     *
     * @param apCreditDetail
     */
    @SneakyThrows
    private void updateApCredit(ApCreditDetail apCreditDetail) {
        DataServiceImpl service = new DataServiceImpl();
        HashMap<String, String> map = new HashMap<>();
        service.UpdateData(Constants.CREDIT, map, apCreditDetail);
    }

    public static void main(String[] args) {
        ERPApCreditController erpApCreditController = new ERPApCreditController();
        erpApCreditController.selectApCredit();
    }
}
